package cn.iocoder.yudao.module.bpm.framework.flowable.exception;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelExceptionConfigTypeEnum;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.flowable.bpmn.model.BaseElement;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;

@Component
@Slf4j
public class ExceptionConfigCheck {

    private final static String EXCEPTION_CONFIG  = "exceptionConfig";

    @Resource
    @Lazy
    private BpmProcessInstanceService processInstanceService;
    @Resource
    @Lazy
    private BpmModelService bpmModelService;

    public ExceptionConfig getTaskExceptionConfig(String processDefinitionId){

        ExceptionConfig exceptionConfig = null;

        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(processDefinitionId);
        BaseElement source = bpmnModel.getMainProcess();
        List<ExtensionElement> bpmExceptionConfig = source.getExtensionElements().get(EXCEPTION_CONFIG);
        if (!CollUtil.isEmpty(bpmExceptionConfig)){
            exceptionConfig = new ExceptionConfig();
            ExtensionElement extensionElement = bpmExceptionConfig.get(0);

            String exceptionEvent = extensionElement.getAttributeValue(null, "exceptionEvent");
            String exceptionEventToUser = extensionElement.getAttributeValue(null, "exceptionEventToUser");


            // 按逗号分割字符串
            String[] strArray = exceptionEventToUser.split(",");

            // 创建一个 long 类型的数组
            ArrayList<Long> ids = new ArrayList<>();

            // 遍历字符串数组，将每个字符串转换为 long 类型
            for (int i = 0; i < strArray.length; i++) {
                if( NumberUtils.isCreatable(strArray[i].trim())){
                    ids.add(Long.parseLong(strArray[i].trim()));
                }
            }

            exceptionConfig.setExceptionEvent(BpmModelExceptionConfigTypeEnum.nameOfType(exceptionEvent));
            exceptionConfig.setExceptionEventToUser(ids);
        }

        return exceptionConfig;
    }

    public void doTaskExceptionConfig(DelegateExecution execution , ExceptionConfig exceptionConfig, Set<Long> assigneeUserIds){

        if(null == exceptionConfig || null == exceptionConfig.getExceptionEvent()
                ||
                (
                    BpmModelExceptionConfigTypeEnum.TO_USER == exceptionConfig.getExceptionEvent()
                        &&
                    exceptionConfig.getExceptionEventToUser().isEmpty()
                )
        ){
            // 2. 校验是否有候选人
            log.error("[calculateUsers][流程任务({}/{}/{}) 找不到候选人]", execution.getId(),
                    execution.getProcessDefinitionId(), execution.getCurrentActivityId());
            throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
        }

        if(BpmModelExceptionConfigTypeEnum.TO_USER == exceptionConfig.getExceptionEvent()){
            assigneeUserIds.addAll(
                    exceptionConfig.getExceptionEventToUser()
            );
        }

    }

}
